// Copyright (c) 2021 Presto Labs Pte. Ltd.
// Author: hyuan

#include "coin2/exchange/btcturk/api_order/native_rest_async_asio_subscriber.h"

namespace coin2::exchange::btcturk::api_order {

namespace {

std::string ToStringArray(const std::set<std::string>& str_set) {
  std::string str_array = "{";
  if (str_set.size() > 0) {
    for (auto itr = str_set.begin(); itr != str_set.end(); ++itr) {
      str_array += "\"" + *itr + "\",";
    }
    str_array = str_array.substr(0, str_array.length() - 1);
  }
  str_array += "}";
  return str_array;
}

}  // namespace

void BtcturkRestAsyncAsioSubscriber::QueryBalance() {
  RestParams params;
  auto http_context = rest_client()->QueryAccountBalance();
  if (!http_context) return;
  http_context->handler =
      std::bind(&BtcturkRestAsyncAsioSubscriber::HandleQuery, this, std::placeholders::_1);
  http_driver_->PostAsyncContext(http_context);
}

void BtcturkRestAsyncAsioSubscriber::QueryOpenOrders(const std::string& native_symbol) {
  RestParams params;
  params.set_pair_symbol(native_symbol);
  auto http_context = rest_client()->QueryOpenOrders(params);
  if (!http_context) return;
  http_context->handler =
      std::bind(&BtcturkRestAsyncAsioSubscriber::HandleQuery, this, std::placeholders::_1);
  http_driver_->PostAsyncContext(http_context);
}

void BtcturkRestAsyncAsioSubscriber::QueryHistoryOrders(const std::string& native_symbol) {
  RestParams params;
  params.set_pair_symbol(native_symbol);
  auto http_context = rest_client()->QueryHistoryOrders(params);
  if (!http_context) return;
  http_context->handler =
      std::bind(&BtcturkRestAsyncAsioSubscriber::HandleQuery, this, std::placeholders::_1);
  http_driver_->PostAsyncContext(http_context);
}

void BtcturkRestAsyncAsioSubscriber::QueryFills(const std::string& currency_array) {
  RestParams params;
  params.set_symbol(currency_array);
  params.set_type("{\"buy\",\"sell\"}");
  auto http_context = rest_client()->QueryFills(params);
  if (!http_context) return;
  http_context->handler =
      std::bind(&BtcturkRestAsyncAsioSubscriber::HandleQuery, this, std::placeholders::_1);
  http_driver_->PostAsyncContext(http_context);
}

void BtcturkRestAsyncAsioSubscriber::SubscribeAsync() {
  AddPeriodicTask(
      std::bind(&BtcturkRestAsyncAsioSubscriber::QueryBalance, this),
      config_.query_account_balance_period_sec(),
      "query_balance");

  auto symbol_list = native_symbols();
  AddPeriodicTask(
      std::bind(&BtcturkRestAsyncAsioSubscriber::QueryOpenOrders, this, std::placeholders::_1),
      config_.query_open_orders_period_sec(),
      "query_open_orders",
      symbol_list);

  AddPeriodicTask(
      std::bind(&BtcturkRestAsyncAsioSubscriber::QueryHistoryOrders, this, std::placeholders::_1),
      std::bind(
          &BtcturkRestAsyncAsioSubscriber::SkipQuery,
          this,
          "query_history_orders",
          std::placeholders::_1),
      config_.query_cancel_orders_period_sec(),
      "query_history_orders",
      symbol_list);

  std::set<std::string> currencies;
  for (const auto* currency : symcache_->GetCurrencies()) {
    currencies.emplace(currency->order_currency());
  }

  // TODO(hyuan): Further test is required.
  AddPeriodicTask(
      std::bind(&BtcturkRestAsyncAsioSubscriber::QueryFills, this, ToStringArray(currencies)),
      config_.query_fill_period_sec(),
      "query_fills");
}

}  // namespace coin2::exchange::btcturk::api_order
